#include <iostream>
#include <string>

/// @brief 注入类名示例
template <class T> struct Y {
  void g();
};

/// @brief 举例类
/// @tparam T
template <typename T> class Person {
public:
  Person() = default;
  Person(const std::string &name, T age) : name(name), age(age) {}
  Person(const std::string &name, T age, T secret_age)
      : name(name), age(age), secret_age(secret_age) {}

  const std::string &getName() const { return name; }
  T getAge() const { return age; }

  void setName(const std::string &n) { name = n; }
  void setAge(T a) { age = a; }

  void walk();
  /// @brief 打印私有成员
  /// @details 注意泛型参数重写，不能用同一个
  /// @tparam U
  /// @param p
  template <typename U> friend void print_private(const Person<U> &p);

protected:
  std::string name;
  T age;

private:
  T secret_age;
};

void class_declaration();
void class_constructor();
void injected_class_name();
void class_example();
void friend_function();